package tripx.plan;

import java.util.ArrayList;
import java.util.HashMap;

import tripx.system.Logger;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;

/**
 * A wrapper for the standard PlanService
 * 
 * @author zhb
 * 
 */
public class PlanServiceWrapper {

	private PlanService service;

	private Logger logger;

	public PlanServiceWrapper() {
		service = new PlanService();
		logger = Logger.getInstance();
	}

	/**
	 * add a new plan to the database.
	 * 
	 * @param jsonPlan
	 *            a json string which represent the PlanPO
	 * @return a boolean value to tell the status
	 */
	public boolean addPlan(String jsonPlan) {
		logger.info("Get Request: Add Plan");
		logger.info("\tReceived: " + jsonPlan);
		PlanPO planPO = new Gson().fromJson(jsonPlan, PlanPO.class);
		// translate it into the DbPlan && DbPlanCity
		int uid = service.queryInteger("getUserIdByName", planPO.getUserName());
		HashMap<Integer, Integer> cidMap = new HashMap<Integer, Integer>();
		for (String cityName : planPO.getCityNames()) {
			int cid = service.queryInteger("getCityIdByName",
					cityName.substring(cityName.indexOf('@') + 1));
			int seq = Integer.parseInt(cityName.substring(0,
					cityName.indexOf('@')));
			if (cid != -1) {
				// if it is valid
				cidMap.put(cid, seq);
			}
		}
		DbPlan plan = new DbPlan(uid, planPO.getBeginDate(),
				planPO.getEndDate(), planPO.getContent(), planPO.getJoin() ? 0
						: 1);
		boolean status = service.addPlan(plan);
		if (status) {
			// ugly....
			int pid = service.queryInteger("getPlanId", uid + "", plan.start,
					plan.end);
			for (int cid : cidMap.keySet()) {
				service.addPlanCity(new DbPlanCity(pid, cid, cidMap.get(cid)));
			}
			logger.info("\tResponse: " + true);
			return true;
		}
		logger.info("\tResponse: " + false);
		return false;
	}

	/**
	 * delete the specified PlanPO
	 * 
	 * @param jsonPlan
	 *            a json string which represent the PlanPO
	 * @return a boolean value to tell the status
	 */
	public boolean deletePlan(String jsonPlan) {
		logger.info("Get Request: Delete Plan");
		logger.info("\tReceived: " + jsonPlan);
		PlanPO planPO = new Gson().fromJson(jsonPlan, PlanPO.class);
		int uid = service.queryInteger("getUserIdByName", planPO.getUserName());
		if (uid != -1) {
			int pid = service.queryInteger("getPlanId", uid + "",
					planPO.getBeginDate(), planPO.getEndDate());
			if (pid != -1) {
				service.deletePlan("pid", pid + "");
				// delete the items on the plancity table
				service.deletePlanCity("pid", pid + "");
				logger.info("\tResponse: " + true);
				return true;
			}
		}
		logger.info("\tResponse: " + false);
		return false;
	}

	/**
	 * modify an exist plan. (!!!Ugly implementation!!!)
	 * 
	 * @param jsonPlanOld
	 *            the previous plan po
	 * @param jsonPlanNew
	 *            the updated plan po
	 * @return
	 */
	public boolean modifyPlan(String jsonPlanOld, String jsonPlanNew) {
		return deletePlan(jsonPlanOld) && addPlan(jsonPlanNew);
	}

	/**
	 * given the city name and retrieve all the plans which is related to this
	 * city
	 * 
	 * @param cityName
	 * @return
	 */
	public String searchPlanByCityName(String cityName) {
		Gson gson = new Gson();
		// get the city id
		int cid = service.queryInteger("getCityIdByName", cityName);
		if (cid == -1) {
			return new Gson().toJson(null);
		}
		// get the pid list
		ArrayList<Integer> pidList = service.queryIntegerList(false,
				"getPlanIdListByCityId", cid + "");
		ArrayList<PlanPO> resultList = new ArrayList<PlanPO>();
		for (int pid : pidList) {
			String result = service.query("getPlanById", pid + "");

			JsonParser parser = new JsonParser();
			JsonArray array = parser.parse(result).getAsJsonArray();
			if (array.size() != 1) {
				return gson.toJson(null);
			}
			DbPlan plan = gson.fromJson(array.get(0), DbPlan.class);
			// we need to ignore the single
			if (plan.single == 1) {
				continue;
			}
			String planCityResult = service.query("getPlanCityByPlanId", pid
					+ "");
			JsonArray planCityArray = parser.parse(planCityResult)
					.getAsJsonArray();
			ArrayList<String> cityNames = new ArrayList<String>();
			for (JsonElement ele : planCityArray) {
				DbPlanCity planCity = gson.fromJson(ele, DbPlanCity.class);
				String cname = service.queryString("getCityNameById",
						planCity.cid + "");
				if (cname != null) {
					cityNames.add(planCity.seq + "@" + cname);
				}
			}
			String uname = service
					.queryString("getUserNameById", plan.uid + "");
			PlanPO po = new PlanPO(uname, plan.start, plan.end, cityNames,
					plan.content, true);
			resultList.add(po);
		}
		// the type is ArrayList
		return gson.toJson(resultList);
	}

	public String searchPlanByUserName(String userName) {
		Gson gson = new Gson();
		// get the user id
		int uid = service.queryInteger("getUserIdByName", userName);
		if (uid == -1) {
			return new Gson().toJson(null);
		}
		// get the pid list
		ArrayList<Integer> pidList = service.queryIntegerList(false,
				"getPlanIdListByUserId", uid + "");
		ArrayList<PlanPO> resultList = new ArrayList<PlanPO>();
		for (int pid : pidList) {
			String result = service.query("getPlanById", pid + "");
			System.out.println(result);

			JsonParser parser = new JsonParser();
			JsonArray array = parser.parse(result).getAsJsonArray();
			if (array.size() != 1) {
				return gson.toJson(null);
			}
			DbPlan plan = gson.fromJson(array.get(0), DbPlan.class);
			String planCityResult = service.query("getPlanCityByPlanId", pid
					+ "");
			JsonArray planCityArray = parser.parse(planCityResult)
					.getAsJsonArray();
			ArrayList<String> cityNames = new ArrayList<String>();
			for (JsonElement ele : planCityArray) {
				DbPlanCity planCity = gson.fromJson(ele, DbPlanCity.class);
				String cname = service.queryString("getCityNameById",
						planCity.cid + "");
				if (cname != null) {
					cityNames.add(planCity.seq + "@" + cname);
				}
			}
			String uname = service
					.queryString("getUserNameById", plan.uid + "");
			PlanPO po = new PlanPO(uname, plan.start, plan.end, cityNames,
					plan.content, true);
			resultList.add(po);
		}
		// the type is ArrayList
		return gson.toJson(resultList);
	}
}
